import datetime
from flask import request, g, jsonify, current_app
from app import db, redis
from app.api_v1_0 import api
from app.utils.commons import login_required
from app.utils.response_code import RET


@api.route("/orders", methods=["POST"])
@login_required
def save_order():
    """保存订单"""
    user_id = g.user_id  # 获取当前登录用户的ID

    # 获取参数
    order_data = request.get_json()  # 获取请求的JSON数据
    if not order_data:
        return jsonify(errno=RET.PARAMERR, errmsg="参数错误")  # 如果参数为空，返回参数错误

    house_id = order_data.get("house_id")  # 预订的房屋编号
    start_date_str = order_data.get("start_date")  # 预订的起始时间
    end_date_str = order_data.get("end_date")  # 预订的结束时间

    # 参数检查
    if not all((house_id, start_date_str, end_date_str)):
        return jsonify(errno=RET.PARAMERR, errmsg="参数错误")

    # 日期格式检查
    try:
        # 将请求的时间参数字符串转换为datetime类型
        start_date = datetime.datetime.strptime(start_date_str, "%Y-%m-%d")
        end_date = datetime.datetime.strptime(end_date_str, "%Y-%m-%d")
        assert start_date <= end_date  # 确保起始时间早于或等于结束时间
        # 计算预订的天数
        days = (end_date - start_date).days + 1  # 计算预订天数
    except Exception as e:
        current_app.logger.error(e)  # 记录错误日志
        return jsonify(errno=RET.PARAMERR, errmsg="日期格式错误")  # 返回日期格式错误

    # 查询房屋是否存在
    try:
        house = House.query.get(house_id)  # 根据房屋ID查询房屋
    except Exception as e:
        current_app.logger.error(e)  # 记录错误日志
        return jsonify(errno=RET.DBERR, errmsg="获取房屋信息失败")  # 返回获取房屋信息失败
    if not house:
        return jsonify(errno=RET.NODATA, errmsg="房屋不存在")  # 如果房屋不存在，返回房屋不存在

    # 预订的房屋是否是房东自己的
    if user_id == house.user_id:
        return jsonify(errno=RET.ROLEERR, errmsg="不能预订自己的房屋")  # 如果预订的房屋是房东自己的，返回错误

    # 确保用户预订的时间内，房屋没有被别人下单
    try:
        # 查询时间冲突的订单数
        count = Order.query.filter(Order.house_id == house_id, Order.begin_date <= end_date,
                                   Order.end_date >= start_date).count()  # 查询订单冲突的数量
        # select count(*) from order where ....
    except Exception as e:
        current_app.logger.error(e)  # 记录错误日志
        return jsonify(errno=RET.DBERR, errmsg="检查出错，请稍候重试")  # 返回检查出错
    if count > 0:
        return jsonify(errno=RET.DATAERR, errmsg="房屋已被预订")  # 如果存在冲突订单，返回房屋已被预订

    # 订单总额
    amount = days * house.price  # 计算订单总额

    # 保存订单数据
    order = Order(
        house_id=house_id,  # 房屋ID
        user_id=user_id,  # 用户ID
        begin_date=start_date,  # 起始日期
        end_date=end_date,  # 结束日期
        days=days,  # 天数
        house_price=house.price,  # 房屋价格
        amount=amount  # 订单总额
    )
    try:
        db.session.add(order)  # 添加订单到数据库会话
        db.session.commit()  # 提交会话
    except Exception as e:
        current_app.logger.error(e)  # 记录错误日志
        db.session.rollback()  # 回滚会话
        return jsonify(errno=RET.DBERR, errmsg="保存订单失败")  # 返回保存订单失败
    return jsonify(errno=RET.OK, errmsg="OK", data={"order_id": order.id})  # 返回成功响应及订单ID


@api.route("/user/orders", methods=["GET"])
@login_required
def get_user_orders():
    """查询用户的订单信息"""
    user_id = g.user_id  # 获取当前登录用户的ID

    role = request.args.get("role", "")  # 获取查询角色参数，判断是房客还是房东

    try:
        if "landlord" == role:
            houses = House.query.filter(House.user_id == user_id).all()  # 查询当前用户作为房东的所有房屋
            houses_ids = [house.id for house in houses]  # 获取这些房屋的ID列表
            orders = Order.query.filter(Order.house_id.in_(houses_ids)).order_by(
                Order.create_time.desc()).all()  # 查询这些房屋的所有订单，并按创建时间降序排序
        else:
            orders = Order.query.filter(Order.user_id == user_id).order_by(
                Order.create_time.desc()).all()  # 查询当前用户作为房客预订的所有订单，并按创建时间降序排序
    except Exception as e:
        current_app.logger.error(e)  # 记录错误日志
        return jsonify(errno=RET.DBERR, errmsg="查询订单信息失败")  # 返回查询订单信息失败

    orders_dict_list = []  # 初始化订单字典列表
    if orders:
        for order in orders:  # 遍历订单
            orders_dict_list.append(order.to_dict())  # 将订单对象转换为字典并添加到列表中

    return jsonify(errno=RET.OK, errmsg="OK", data={"orders": orders_dict_list})  # 返回订单数据

@api.route("/orders/<int:order_id>/status", methods=["PUT"])  # 定义一个PUT请求的路由，用于处理订单状态
@login_required  # 需要用户登录才能访问此路由
def accept_reject_order(order_id):
    """接单、拒单"""
    user_id = g.user_id  # 获取当前登录用户的ID

    req_data = request.get_json()  # 获取请求的JSON数据
    if not req_data:  # 判断请求数据是否为空
        return jsonify(errno=RET.PARAMERR, errmsg="参数错误")  # 返回参数错误

    action = req_data.get("action")  # 获取action参数，表示接单或拒单的行为
    if action not in ("accept", "reject"):  # 判断action参数是否有效
        return jsonify(errno=RET.PARAMERR, errmsg="参数错误")  # 返回参数错误

    try:
        order = Order.query.filter(Order.id == order_id, Order.status == "WAIT_ACCEPT").first()  # 查询符合条件的订单
        house = order.house  # 获取订单对应的房屋
    except Exception as e:
        current_app.logger.error(e)  # 记录错误日志
        return jsonify(errno=RET.DBERR, errmsg="无法获取订单数据")  # 返回无法获取订单数据

    if not order or house.user_id != user_id:  # 判断订单是否存在且是否为当前用户的房屋
        return jsonify(errno=RET.REQERR, errmsg="操作无效")  # 返回操作无效

    if action == "accept":
        order.status = "WAIT_PAYMENT"  # 更新订单状态为等待支付
    elif action == "reject":
        reason = req_data.get("reason")  # 获取拒单原因
        if not reason:  # 判断拒单原因是否为空
            return jsonify(errno=RET.PARAMERR, errmsg="参数错误")  # 返回参数错误
        order.status = "REJECTED"  # 更新订单状态为拒绝
        order.comment = reason  # 保存拒单原因

    try:
        db.session.add(order)  # 添加订单到数据库会话
        db.session.commit()  # 提交数据库会话
    except Exception as e:
        current_app.logger.error(e)  # 记录错误日志
        db.session.rollback()  # 回滚数据库会话
        return jsonify(errno=RET.DBERR, errmsg="操作失败")  # 返回操作失败 

    return jsonify(errno=RET.OK, errmsg="OK")  # 返回操作成功

@api.route("/orders/<int:order_id>/comment", methods=["PUT"])  # 定义一个PUT请求的路由，用于保存订单评论信息
@login_required  # 需要用户登录才能访问此路由
def save_order_comment(order_id):
    """保存订单评论信息"""
    user_id = g.user_id  # 获取当前登录用户的ID

    # 获取参数
    req_data = request.get_json()  # 获取请求的JSON数据
    comment = req_data.get("comment")  # 获取评价信息

    # 检查参数
    if not comment:  # 判断评价信息是否为空
        return jsonify(errno=RET.PARAMERR, errmsg="参数错误")  # 返回参数错误

    try:
        # 需要确保只能评论自己下的订单，而且订单处于待评价状态才可以
        order = Order.query.filter(Order.id == order_id, Order.user_id == user_id,
                                   Order.status == "WAIT_COMMENT").first()  # 查询符合条件的订单
        house = order.house  # 获取订单对应的房屋
    except Exception as e:
        current_app.logger.error(e)  # 记录错误日志
        return jsonify(errno=RET.DBERR, errmsg="无法获取订单数据")  # 返回无法获取订单数据

    if not order:  # 判断订单是否存在且是否为当前用户的订单
        return jsonify(errno=RET.REQERR, errmsg="操作无效")  # 返回操作无效

    try:
        # 将订单的状态设置为已完成
        order.status = "COMPLETE"  # 更新订单状态为已完成
        # 保存订单的评价信息
        order.comment = comment  # 保存评价信息
        # 将房屋的完成订单数增加1
        house.order_count += 1  # 增加房屋的完成订单数
        db.session.add(order)  # 添加订单到数据库会话
        db.session.add(house)  # 添加房屋到数据库会话
        db.session.commit()  # 提交数据库会话
    except Exception as e:
        current_app.logger.error(e)  # 记录错误日志
        db.session.rollback()  # 回滚数据库会话
        return jsonify(errno=RET.DBERR, errmsg="操作失败")  # 返回操作失败

    # 因为房屋详情中有订单的评价信息，为了让最新的评价信息展示在房屋详情中，所以删除redis中关于本订单房屋的详情缓存
    try:
        redis.delete("house_info_%s" % order.house.id)  # 删除缓存中的房屋详情信息
    except Exception as e:
        current_app.logger.error(e)  # 记录错误日志

    return jsonify(errno=RET.OK, errmsg="OK")  # 返回操作成功